package com.jakeprim.reflection;

import com.jakeprim.annotation.Study;
import com.jakeprim.model.Person;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectionDemo {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //1 通过反射获取到class类的元信息
        Person person = new Person();
        Class<? extends Person> aClass = person.getClass();//获取到class对象 类的元信息
        //其他方式反射
        Class<?> aClass1 = Class.forName("com.jakeprim.model.Person");//spring
        //<bean name="", class="com.jakeprim.model.Person" />
        //2 通过反射获取类名 包名
        String name = aClass1.getName();//全类名
        String simpleName = aClass1.getSimpleName();//类名
        System.out.println("simpleName:" + simpleName);
        System.out.println("name:" + name);
        System.out.println("aClass1:" + aClass1);
        System.out.println("aClass:" + aClass);

        //3 获取类的属性
        Field[] declaredFields = aClass.getDeclaredFields();//获取类的所有属性
        for (Field field : declaredFields) {
            System.out.println(field);
        }
        //获取指定的属性
        Field ageField = aClass.getDeclaredField("age");
        System.out.println("ageField:" + ageField);
        //4 获取到属性的具体值
        person.setName("jakeprim");
        person.setAge(18);
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);//设置属性为可见
            System.out.println(declaredField.get(person));
        }

        //4 另一种写法
        Object p = aClass.newInstance();//相当于在反射中实例化
        for (Field field : declaredFields) {
            field.setAccessible(true);
            if (field.getName().equals("name")) {
                field.set(p, "kane");
            } else {
                field.set(p, 18);
            }
            System.out.println(field.get(p));
        }

        //5 反射获取方法 并执行方法
        Method[] methods = aClass.getMethods();//获取所有方法
        for (Method method : methods) {
//            System.out.println(method.getName());
        }
        //获取指定的方法
        Method method = aClass.getMethod("getString");//方法名 参数类型
        Object invoke = method.invoke(p);//传递：类对象 参数值 并执行方法
        System.out.println(invoke);

        //6 通过反射获得类的注解
        Study study = aClass.getAnnotation(Study.class);
        //获取注解的内容
        String[] moves = study.moves();
        String name1 = study.name();
        System.out.println("moves:" + moves[0] + " name:" + name1);

        //7 从方法上获得注解
        Study methodAnnotation = method.getAnnotation(Study.class);
        String[] methodMoves = methodAnnotation.moves();
        String methodName1 = methodAnnotation.name();
        System.out.println("get method annotation moves:" + methodMoves[0] + " methodName1:" + methodName1);

        //8 从属性上获得注解
        for (Field field : declaredFields) {
            Study fieldAnnotation = field.getAnnotation(Study.class);
            if (fieldAnnotation == null) {
                continue;
            }
            System.out.println("get fields annotation moves:" + fieldAnnotation.moves()[0] + " name:" + fieldAnnotation.name());
        }
        Study ageAnnotation = ageField.getAnnotation(Study.class);
        System.out.println("ageAnnotation:"+ageAnnotation.moves()[0]);
    }
}
